/*
 * 维护坐标信息的类
 * z轴坐标代表图层，不参与距离计算。
 */

#ifndef AI9_LOGIC_2017_POINT_H
#define AI9_LOGIC_2017_POINT_H
#include <iostream>
#include <cmath>
class Point{
public:
    int x, y, z = 0;
    Point(int _x = 0, int _y = 0, int _z = 0):x(_x), y(_y), z(_z){}
    static inline Point fromString(std::string str){
        int _x = 0, _y = 0, _z = 0;
        sscanf(str.c_str(), "(%d, %d, %d)", &_x, &_y, &_z);
        return Point(_x, _y, _z);
    };
    inline const std::string to_string() const{
        return "(" + std::to_string(x) + ", " + std::to_string(y) + ", " + std::to_string(z) + ")";
    }
	inline int getManhattanLength() const{
		return std::abs(x) + std::abs(y);
	}
	inline double getEuclideanLength() const{
		return std::pow(std::pow(x, 2.0) + std::pow(y, 2.0), 0.5);
	}
	inline int getSquaredEuclideanLength() const{
		return x * x + y * y;
	}
	inline Point operator +(const Point &other) const{
		return Point(x + other.x, y + other.y/*, z*/);
	}
	inline Point operator -(const Point &other) const{
		return Point(x - other.x, y - other.y/*, z*/);
	}
};

inline bool operator<(const Point& foo, const Point& bar){
    return foo.x != bar.x ? foo.x < bar.x :
           (foo.y != bar.y ? foo.y < bar.y : foo.z < bar.z);
}

inline std::ostream& operator << (std::ostream& os, const Point& p){
    return os << p.to_string();
}

inline double getEuclideanDist(const Point& foo, const Point& bar){
    return std::pow(std::pow(foo.x - bar.x, 2.0) + std::pow(foo.y - bar.y, 2.0), 0.5);
}

inline int getManhattanDist(const Point& foo, const Point& bar){
    return std::abs(foo.x - bar.x) + std::abs(foo.y - bar.y);
}

inline int getSquaredEuclideanDist(const Point& foo, const Point& bar){
    return (foo.x - bar.x) * (foo.x - bar.x) + (foo.y - bar.y) * (foo.y - bar.y);
}

#endif //AI9_LOGIC_2017_POINT_H
